import string, random
from ..functions.marketing_coupon_func import MarketingCouponFunc
from odoo.exceptions import UserError
from ...rp_customer_management.functions.flow_log_functions import FlowLogFunctions


class MarketingRewardScheduleFunc(object):
    """
    Model:
        满足所有营销任务和邀请推广任务的算法逻辑

    Param:
        -env:odoo env
    """

    def __init__(self, env):
        self.env = env

    def generator_invite_task(self, rule_id, person):
        """
        生成邀请码和邀请任务（用户进行绑定邀请码和奖励规则）
        适用条件：已注册的用户
        Params:
        -rule_id:奖励规则ID
        -person:已注册的用户
        Condition：
        1 没有绑定邀请码和规则的会进行新建
        2 已经绑定过同一类型的邀请码，规则模板中这一类型变动了规则
               a 同类型下该用户从未根据该规则生成过任务【邀请码复用，失效之前的邀请任务，添加新的邀请任务】
               b 同类型下该用户根据该规则生成过任务，只不过中途失效，后又重新手动生效 【激活之前的邀请任务】
        """
        characters = string.ascii_uppercase + string.digits
        code = rule_id.invite_category_id.invite_code_prefix + ''.join(random.choice(characters) for i in range(9))
        invite_number = 0
        if not rule_id:
            return
        # 客户是否已存在注册邀请码
        existed_invited_code = person.invite_code_ids.filtered(lambda r: r.invite_category_id.id == rule_id.invite_category_id.id)
        # 查找相同类型下的有效邀请码，获取邀请人数（有且只有一个）
        if len(existed_invited_code) > 0:
            invite_number = existed_invited_code.filtered(lambda r: r.validate_flag)[0].invite_number
        # 客户任务中是否已经存在相同类型和相同规则的任务记录【有且只有一个】
        existed_invited_code_rule = existed_invited_code.filtered(lambda r: r.rp_reward_incentive_rule_id.id == rule_id.id)
        # 所有注册任务失效
        if len(existed_invited_code.ids) > 0:
            for record in existed_invited_code:
                record.write({'validate_flag': False})
        # 历史记录中存在该分类和规则下的失效Record，将其激活
        if len(existed_invited_code_rule.ids) == 1 and not existed_invited_code_rule.validate_flag:
            existed_invited_code_rule.write({'validate_flag': True, 'invite_number': invite_number})
        # 不存在该分类和规则下的记录进行创建
        elif len(existed_invited_code_rule.ids) == 0:
            # 存在同类别的记录，复用邀请码
            if len(existed_invited_code.ids) > 0:
                code = existed_invited_code[0].invite_code
            data = {
                'rp_customer_id': person.id,
                'rp_reward_incentive_rule_id': rule_id.id,
                'invite_code': code,
                'invite_category_id': rule_id.invite_category_id.id,
                'invite_number': invite_number
            }
            self.env['rp.invite.schedule'].create([data])
        else:
            existed_invited_code_rule.write({'validate_flag': True})

    def gain_reward_related_invite(self, invite_code, category_id, invited_person):
        """
        邀请人和被邀请人获得奖励
        Params:
        -invite_code:邀请码
        -category_id:邀请分类
        -invited_person:被邀请人
        """
        if category_id in invited_person.earn_invite_category.ids:
            raise UserError('您已经获得此活动的奖励，不可以重复获得！')
        result = self.env['rp.invite.schedule'].search([('invite_code', '=', invite_code), ('invite_category_id', '=', category_id.id), ('validate_flag', '=', True)])
        if not result:
            raise UserError('您输入的邀请码不合法！')
        invite_number = result.invite_number + 1
        result.write({'invite_number': invite_number})
        # 被邀请方获得奖励
        reward_rule = result.rp_reward_incentive_rule_id
        # 返余额
        if reward_rule.cash_back_tag:
            invited_person.write({'remaining_sum': invited_person.remaining_sum + reward_rule.invited_cash_back_price})
            # 生成流水
            self.generate_flow_log(invited_person, reward_rule, '被邀请者')
        # 获得优惠券
        if reward_rule.coupon_tag:
            coupon_ids = reward_rule.rp_selected_coupon_line_ids
            for coupon_id in coupon_ids:
                for i in range(coupon_id.amount):
                    MarketingCouponFunc(self.env).issue_coupon_to_customer(coupon_id.rp_coupon_template_id, invited_person)
        invited_person.write({'earn_invite_category': [(4, category_id.id)]})
        # 邀请方获得奖励
        gradient_template_id = reward_rule.rp_reward_gradient_template_ids.filtered(lambda r: r.invite_number == invite_number)
        if len(gradient_template_id) == 1:
            # 返佣金
            if gradient_template_id.cash_back_tag:
                reward_before = result.rp_customer_id.remaining_sum
                result.rp_customer_id.write({'remaining_sum': reward_before + gradient_template_id.invite_cash_back_price})
                # 生成流水
                self.generate_flow_log(result.rp_customer_id, reward_rule, '邀请者')
            # 返券
            if gradient_template_id.coupon_tag:
                for coupon_id in gradient_template_id.rp_selected_coupon_line_ids:
                    for i in range(coupon_id.amount):
                        MarketingCouponFunc(self.env).issue_coupon_to_customer(coupon_id.rp_coupon_template_id, result.rp_customer_id)

    def handle_history_record_for_write(self, invite_category_id, values, id=None):
        """
       邀请规则历史记录校验
       Params:
       - invite_category_id:邀请规则类型
       - id:邀请规则ID
       -values:更新的记录
       """
        equal_ids = None
        if id is not None:
            base_search_ids = self.env['rp.reward.incentive.rule'].search([('invite_category_id', '=', invite_category_id), ('id', '!=', id), ('rule_state', '=', 'done')])
        else:
            base_search_ids = self.env['rp.reward.incentive.rule'].search([('invite_category_id', '=', invite_category_id), ('code', '!=', values.get('code')), ('rule_state', '=', 'done')])
        # 只有等级和分类都存在交集时才不允许创建
        if values.get('customer_level_ids') and values.get('customer_category_ids'):
            levels_and_categories_conflict = base_search_ids.filtered(lambda r: set(r.customer_level_ids.ids) & set(values.get('customer_level_ids')[0][2])
                                                                                and set(r.customer_category_ids.ids) & set(values.get('customer_category_ids')[0][2]))
            equal_ids = base_search_ids.filtered(lambda r: set(r.customer_level_ids.ids) == set(values.get('customer_level_ids')[0][2])
                                                           and set(r.customer_category_ids.ids) == set(values.get('customer_category_ids')[0][2]))
            if len(levels_and_categories_conflict) > 0 and len(equal_ids) == 0:
                levels_and_categories_conflict_codes = levels_and_categories_conflict.mapped(lambda r: r.code) if levels_and_categories_conflict else []
                difference_record_codes = '[ ' + ','.join(set(levels_and_categories_conflict_codes)) + ']'
                raise UserError(f' {difference_record_codes} 和本规则存在冲突，解决后重试!   (处理等级或分类冲突)')
        return equal_ids

    def handle_history_record(self, invite_category_id, customer_category_ids, customer_level_ids, id):
        """
       邀请规则历史记录校验
       Params:
       - invite_category_id:邀请规则类型
       - id:邀请规则ID
       -values:更新的记录
       """
        base_search_ids = self.env['rp.reward.incentive.rule'].search([('invite_category_id', '=', invite_category_id), ('id', '!=', id), ('rule_state', '=', 'done')])
        if customer_level_ids != [] and customer_category_ids != []:
            # 存在交集的记录
            # 只有等级和分类都存在交集时才不允许创建
            levels_and_categories_conflict = base_search_ids.filtered(lambda r: set(r.customer_level_ids.ids) & set(customer_level_ids) and set(r.customer_category_ids.ids) & set(customer_category_ids))
            # 相同的记录
            equal_ids = base_search_ids.filtered(lambda r: set(r.customer_level_ids.ids) == set(customer_level_ids) and set(r.customer_category_ids.ids) == set(customer_category_ids))
            if len(levels_and_categories_conflict) > 0 and len(equal_ids) == 0:
                levels_categories_conflict_codes = levels_and_categories_conflict.mapped(lambda r: r.code) if levels_and_categories_conflict else []
                difference_record_codes = '[ ' + ','.join(set(levels_categories_conflict_codes)) + ']'
                raise UserError(f' {difference_record_codes} 和本规则存在冲突，解决后重试!   (处理等级或分类冲突)')
        else:
            raise UserError('配置错误！')
        return equal_ids

    def generate_flow_log(self, customer, reward_rule, tag_str):
        """
        生成流水
        Params:
        -customer:用户
        -reward_rule:奖励规则
        -tag_str:标志字符
        """
        category_id = self.env['rp.flow.record.category'].search([('name', '=', '营销'), ('category_type', '=', 'L1')])
        sec_category_id = self.env['rp.flow.record.category'].search([('name', '=', '注册'), ('category_type', '=', 'L2')])
        data_flow_lines = {
            'flow_record_category_id': sec_category_id.id,
            'change_type': 'add',
            'funds_change': reward_rule.invited_cash_back_price,
            'desc': f'{tag_str}（{customer.name}） 获得：{reward_rule.invited_cash_back_price}€'
        }
        data = {
            'rp_customer_id': customer.id,
            'category_id': category_id.id,
            'change_type': 'add',
            'funds_change': reward_rule.invited_cash_back_price,
            'rp_flow_record_log_line_ids': [(0, 0, data_flow_lines)]
        }
        FlowLogFunctions(self.env).save_flow_log(**data)
        return category_id
